#include "BreakPointService.h"
#include <cassert>
#include "Message.h"
#include "Backend.h"

// service start: seqno = 0
// service connected:
//      send remote backend login_request(with current seqno)
//      , and then backend send login_response to this service;
// received --> 1. receive login response
//							not consume the seqNo
//          --> 2. receive normal response:  
//						checkout seqNo + 1 = msg.seqNo ; OK=> seqNo += 1; failed->ret -1;
// service disconnected: nothing
// service stop:
//	seqNo = 0;

int BreakPointService::start() { 
  _seqNo = 0;
  return 0;
}
int BreakPointService::getBreakpoint() {
  return _seqNo ;
}

//maybe need to exception test 
int BreakPointService::sendMessage(const Message & msg){
  if(_backend != nullptr){
    return _backend->receiveLoginMessage(msg);
  }
  return -1;
}

int BreakPointService::connected(){
  Message login(_seqNo, LOGIN_REQUEST, "loginRequest"); 
  return sendMessage(login);
}
int BreakPointService::disconnected(){
  return 0;
}

int BreakPointService::receiveNormalResponse(const Message & msg){
  if(_seqNo + 1 == msg.seqNo()){
    _seqNo ++;
    return 0;
  }
  return -1;
}
int BreakPointService::receiveLoginResponse(const Message & loginMsg){
  if(loginMsg.type() != LOGIN_RESPONSE){
    return -1;
  }
  return 0;
}

int BreakPointService::stop(){
  _seqNo = 0;
  return 0;
}

void test_breakpoint_service__load_not_exist_file(){
  Backend backend;
	const char * fileName = "seq.breakpoint.txt"
	//TODO: file::remove(fileName)
  BreakPointService service(&backend, fileName);

  assert(0 == service.start()); 
  assert(0 == service.getBreakpoint());
}

void test_...._service_restart(){
  Backend backend;
	const char * fileName = "seq.breakpoint.txt"
  BreakPointService service(&backend, fileName);

  assert(0 == service.start()); 
  assert(0 == service.getBreakpoint());

  assert(0 == service.connected());
  assert(backend.receivedBreakPoint() == 0);

  {
    Message msg(1, LOGIN_RESPONSE+1, "hello1");
    assert(msg.seqNo() == 1);

    assert(0 == service.receiveNormalResponse(msg));
    assert(1 == service.getBreakpoint());
  }

	service.stop();
  assert(0 == service.getBreakpoint());

	service.start();
	assert(1 == service.getBreakpoint());
}


void test_breakpoint_service() {
  Backend backend;
	const char * fileName = "seq.breakpoint.txt"
  BreakPointService service(&backend, fileName);

  assert(0 == service.start()); 
  assert(0 == service.getBreakpoint());

  assert(0 == service.connected());
  assert(backend.receivedBreakPoint() == 0);

  {
    Message msg(1, LOGIN_RESPONSE+1, "hello1");
    assert(msg.seqNo() == 1);

    assert(0 == service.receiveNormalResponse(msg));
    assert(1 == service.getBreakpoint());
  }

	service.stop();
  assert(0 == service.getBreakpoint());

	service.start();
	assert(1 == service.getBreakpoint());




  { //Case 2: check error seqno of msg --> received failed 
    Message next_recv_msg(100, LOGIN_RESPONSE + 1, "hello100");
    assert(100 == next_recv_msg.seqNo());
    assert(1 == service.getBreakpoint());
    assert(-1 == service.receiveNormalResponse(next_recv_msg));
  }

  {
    Message msg(2, LOGIN_RESPONSE+1, "hello2");
    assert(0 == service.receiveNormalResponse(msg));
    assert(2 == service.getBreakpoint());
  }

  //login test case 
  {
    Message login(3, LOGIN_RESPONSE, "hello3");
    assert(login.type() == LOGIN_RESPONSE);
    assert(0 == service.receiveLoginResponse(login));
    assert(2 == service.getBreakpoint()); // don't consume the breakpoint
  }

  {
    Message login(3, LOGIN_RESPONSE + 3, "hello3");
    assert(login.type() != LOGIN_RESPONSE);
    assert(-1 == service.receiveLoginResponse(login));
  }


  assert(0 == service.disconnected());

  assert(0 == service.stop());
  assert(0 == service.getBreakpoint());
}
